{
 "cells": [
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 连接查询",
   "id": "3c1e86c422668cb"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-10T06:42:49.159170Z",
     "start_time": "2025-09-10T06:42:48.507735Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import pandas as pd\n",
    "path = 'D:/2506A/monty03/day13/file/'"
   ],
   "id": "fdadd5589fe2fd23",
   "outputs": [],
   "execution_count": 1
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 1. merge()演示",
   "id": "a2945c4acc954fb4"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "# 创建示例数据\n",
    "\n"
   ],
   "id": "823583ff2080f854"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-10T06:55:35.890798Z",
     "start_time": "2025-09-10T06:55:35.859014Z"
    }
   },
   "cell_type": "code",
   "source": [
    "df1 = pd.DataFrame({\n",
    "    '姓名': ['叶问', '李小龙', '刘德华', '李小龙', '叶问', '叶问'],\n",
    "    '出场次数1': [0, 1, 2, 3, 4, 5]\n",
    "})\n",
    "\n",
    "df2 = pd.DataFrame({\n",
    "    '姓名': ['黄飞鸿', '刘德华', '李小龙'],\n",
    "    '出场次数2': [1, 2, 3]\n",
    "})\n",
    "\n",
    "# 内连接\n",
    "result_inner = pd.merge(df1, df2, on='姓名',how='inner')\n",
    "print(result_inner)\n",
    "\n",
    "\n",
    "print('=' * 30)\n",
    "# 左外连接\n",
    "result_left = pd.merge(df1, df2, on='姓名',how='left')\n",
    "print(result_left)\n",
    "\n",
    "print('=' * 30)\n",
    "# 右外连接\n",
    "result_right = pd.merge(df1, df2, on='姓名',how='right')\n",
    "print(result_right)\n",
    "\n",
    "# 全外连接\n",
    "result_outer = pd.merge(df1, df2, on='姓名',how='outer')\n",
    "print(result_outer)"
   ],
   "id": "4c57cabe1fdda69",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "    姓名  出场次数1  出场次数2\n",
      "0  李小龙      1      3\n",
      "1  刘德华      2      2\n",
      "2  李小龙      3      3\n",
      "==============================\n",
      "    姓名  出场次数1  出场次数2\n",
      "0   叶问      0    NaN\n",
      "1  李小龙      1    3.0\n",
      "2  刘德华      2    2.0\n",
      "3  李小龙      3    3.0\n",
      "4   叶问      4    NaN\n",
      "5   叶问      5    NaN\n",
      "==============================\n",
      "    姓名  出场次数1  出场次数2\n",
      "0  黄飞鸿    NaN      1\n",
      "1  刘德华    2.0      2\n",
      "2  李小龙    1.0      3\n",
      "3  李小龙    3.0      3\n",
      "    姓名  出场次数1  出场次数2\n",
      "0  刘德华    2.0    2.0\n",
      "1   叶问    0.0    NaN\n",
      "2   叶问    4.0    NaN\n",
      "3   叶问    5.0    NaN\n",
      "4  李小龙    1.0    3.0\n",
      "5  李小龙    3.0    3.0\n",
      "6  黄飞鸿    NaN    1.0\n"
     ]
    }
   ],
   "execution_count": 8
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-10T07:01:22.761391Z",
     "start_time": "2025-09-10T07:01:22.738937Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 多键连接示例\n",
    "df3 = pd.DataFrame({\n",
    "    '姓名': ['张三', '张三', '王五'],\n",
    "    '班级': ['1班', '2班', '1班'],\n",
    "    '分数': [10, 20, 30]\n",
    "})\n",
    "\n",
    "df4 = pd.DataFrame({\n",
    "    '姓名': ['张三', '张三', '王五', '王五'],\n",
    "    '班级': ['1班', '1班', '1班', '2班'],\n",
    "    '分数': [40, 50, 60, 70]\n",
    "})\n",
    "\n",
    "# 多键 内连接\n",
    "result_inner = pd.merge(df3, df4, on=['班级','姓名'],how='inner')\n",
    "print(result_inner)\n",
    "\n",
    "print('=' * 30)\n",
    "# 指定后缀区分相同的列名\n",
    "result_suffix = pd.merge(df3, df4, on=['班级','姓名'],how='inner',suffixes=('_左','_右'))\n",
    "print(result_suffix)\n"
   ],
   "id": "cfeb3ccd2e06beae",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "   姓名  班级  分数_x  分数_y\n",
      "0  张三  1班    10    40\n",
      "1  张三  1班    10    50\n",
      "2  王五  1班    30    60\n",
      "==============================\n",
      "   姓名  班级  分数_左  分数_右\n",
      "0  张三  1班    10    40\n",
      "1  张三  1班    10    50\n",
      "2  王五  1班    30    60\n"
     ]
    }
   ],
   "execution_count": 13
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-10T07:14:16.072801Z",
     "start_time": "2025-09-10T07:14:16.059882Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 创建员工信息表\n",
    "employees = pd.DataFrame({\n",
    "    '员工id': [1, 2, 3, 4, 5],\n",
    "    '姓名': ['张三', '李四', '王五', '赵六', '钱七'],\n",
    "    '部门id': [101, 102, 101, 103, 102],\n",
    "    '工资': [5000, 6000, 5500, 7000, 6500]\n",
    "})\n",
    "\n",
    "# 创建部门信息表\n",
    "departments = pd.DataFrame({\n",
    "    '部门id': [101, 102, 103, 104],\n",
    "    '部门名称': ['技术部', '销售部', '财务部', '人事部'],\n",
    "    '办公地址': ['北京', '上海', '广州', '深圳']\n",
    "})\n",
    "\n",
    "# # 创建项目信息表\n",
    "# projects = pd.DataFrame({\n",
    "#     '项目id': [1, 2, 3, 4],\n",
    "#     '项目名称': ['项目A', '项目B', '项目C', '项目D'],\n",
    "#     '项目负责人': [1, 2, 3, 6]  # 注意：项目负责人=6在employees中不存在\n",
    "# })\n",
    "\n",
    "print(\"员工表:\")\n",
    "print(employees)\n",
    "print(\"\\n部门表:\")\n",
    "print(departments)\n",
    "# print(\"\\n项目表:\")\n",
    "# print(projects)"
   ],
   "id": "fa79574fd879ad23",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "员工表:\n",
      "   员工id  姓名  部门id    工资\n",
      "0     1  张三   101  5000\n",
      "1     2  李四   102  6000\n",
      "2     3  王五   101  5500\n",
      "3     4  赵六   103  7000\n",
      "4     5  钱七   102  6500\n",
      "\n",
      "部门表:\n",
      "   部门id 部门名称 办公地址\n",
      "0   101  技术部   北京\n",
      "1   102  销售部   上海\n",
      "2   103  财务部   广州\n",
      "3   104  人事部   深圳\n"
     ]
    }
   ],
   "execution_count": 25
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-10T07:14:49.317019Z",
     "start_time": "2025-09-10T07:14:49.300872Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 内连接：只保留两个表都有的部门ID\n",
    "inner_merge = pd.merge(employees, departments, on='部门id', how='inner')\n",
    "print(\"内连接结果:\")\n",
    "print(inner_merge)"
   ],
   "id": "74fcdfb9a148de12",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "内连接结果:\n",
      "   员工id  姓名  部门id    工资 部门名称 办公地址\n",
      "0     1  张三   101  5000  技术部   北京\n",
      "1     2  李四   102  6000  销售部   上海\n",
      "2     3  王五   101  5500  技术部   北京\n",
      "3     4  赵六   103  7000  财务部   广州\n",
      "4     5  钱七   102  6500  销售部   上海\n"
     ]
    }
   ],
   "execution_count": 26
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-10T07:15:01.999559Z",
     "start_time": "2025-09-10T07:15:01.989285Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 左连接：保留所有员工，即使没有部门信息\n",
    "left_merge = pd.merge(employees, departments, on='部门id', how='left')\n",
    "print(\"左连接结果:\")\n",
    "print(left_merge)"
   ],
   "id": "bb665c1176dac5b7",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "左连接结果:\n",
      "   员工id  姓名  部门id    工资 部门名称 办公地址\n",
      "0     1  张三   101  5000  技术部   北京\n",
      "1     2  李四   102  6000  销售部   上海\n",
      "2     3  王五   101  5500  技术部   北京\n",
      "3     4  赵六   103  7000  财务部   广州\n",
      "4     5  钱七   102  6500  销售部   上海\n"
     ]
    }
   ],
   "execution_count": 27
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-10T07:15:15.510927Z",
     "start_time": "2025-09-10T07:15:15.495979Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 右连接：保留所有部门，即使没有员工\n",
    "right_merge = pd.merge(employees, departments, on='部门id', how='right')\n",
    "print(\"右连接结果:\")\n",
    "print(right_merge)"
   ],
   "id": "1bf5a80fb8e9047",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "右连接结果:\n",
      "   员工id   姓名  部门id      工资 部门名称 办公地址\n",
      "0   1.0   张三   101  5000.0  技术部   北京\n",
      "1   3.0   王五   101  5500.0  技术部   北京\n",
      "2   2.0   李四   102  6000.0  销售部   上海\n",
      "3   5.0   钱七   102  6500.0  销售部   上海\n",
      "4   4.0   赵六   103  7000.0  财务部   广州\n",
      "5   NaN  NaN   104     NaN  人事部   深圳\n"
     ]
    }
   ],
   "execution_count": 28
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-10T07:15:29.309346Z",
     "start_time": "2025-09-10T07:15:29.294719Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 外连接：保留所有记录\n",
    "outer_merge = pd.merge(employees, departments, on='部门id', how='outer')\n",
    "print(\"外连接结果:\")\n",
    "print(outer_merge)"
   ],
   "id": "ffc8f0c9f7edd6d3",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "外连接结果:\n",
      "   员工id   姓名  部门id      工资 部门名称 办公地址\n",
      "0   1.0   张三   101  5000.0  技术部   北京\n",
      "1   3.0   王五   101  5500.0  技术部   北京\n",
      "2   2.0   李四   102  6000.0  销售部   上海\n",
      "3   5.0   钱七   102  6500.0  销售部   上海\n",
      "4   4.0   赵六   103  7000.0  财务部   广州\n",
      "5   NaN  NaN   104     NaN  人事部   深圳\n"
     ]
    }
   ],
   "execution_count": 29
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-10T07:18:38.448922Z",
     "start_time": "2025-09-10T07:18:38.433126Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 创建带时间的工资表\n",
    "salary_history = pd.DataFrame({\n",
    "    '员工id': [1, 2, 1, 3, 4],\n",
    "    '年份': [2023, 2023, 2024, 2023, 2023],\n",
    "    '工资': [4800, 5800, 5000, 5500, 7000]\n",
    "})\n",
    "\n",
    "# 多键连接\n",
    "multi_key_merge = pd.merge(\n",
    "    employees,\n",
    "    salary_history,\n",
    "    on=['员工id', '工资'],\n",
    "    how='inner',\n",
    ")\n",
    "print(\"多键连接结果:\")\n",
    "print(multi_key_merge)"
   ],
   "id": "afdaa46e4663baf9",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "多键连接结果:\n",
      "   员工id  姓名  部门id    工资    年份\n",
      "0     1  张三   101  5000  2024\n",
      "1     3  王五   101  5500  2023\n",
      "2     4  赵六   103  7000  2023\n"
     ]
    }
   ],
   "execution_count": 30
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-10T07:18:53.344292Z",
     "start_time": "2025-09-10T07:18:53.332830Z"
    }
   },
   "cell_type": "code",
   "source": [
    "multi_key_merge = pd.merge(\n",
    "    employees,\n",
    "    salary_history,\n",
    "    on='员工id',\n",
    "    how='inner',\n",
    "    suffixes=('_当前', '_历年')\n",
    ")\n",
    "print(\"多键连接结果:\")\n",
    "print(multi_key_merge)"
   ],
   "id": "98532557b16695f0",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "多键连接结果:\n",
      "   员工id  姓名  部门id  工资_当前    年份  工资_历年\n",
      "0     1  张三   101   5000  2023   4800\n",
      "1     1  张三   101   5000  2024   5000\n",
      "2     2  李四   102   6000  2023   5800\n",
      "3     3  王五   101   5500  2023   5500\n",
      "4     4  赵六   103   7000  2023   7000\n"
     ]
    }
   ],
   "execution_count": 31
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 2. Join 基于索引的便捷连接方法 演示",
   "id": "62f6e665d666e5ed"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-10T07:33:48.569819Z",
     "start_time": "2025-09-10T07:33:48.558637Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 创建示例数据\n",
    "left = pd.DataFrame({\n",
    "    'A': ['A0', 'A1', 'A2', 'A3'],\n",
    "    'B': ['B0', 'B1', 'B2', 'B3']\n",
    "}, index=['K0', 'K1', 'K2', 'K3'])\n",
    "\n",
    "\n",
    "right = pd.DataFrame({\n",
    "    'C': ['C0', 'C1', 'C2'],\n",
    "    'D': ['D0', 'D1', 'D2']\n",
    "}, index=['K0', 'K1', 'K2'])\n",
    "\n",
    "# 基于索引的连接\n",
    "result_join = left.join(right)\n",
    "print(result_join)\n",
    "print('=' * 30)\n"
   ],
   "id": "29507fc6a92aac3e",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "     A   B    C    D\n",
      "K0  A0  B0   C0   D0\n",
      "K1  A1  B1   C1   D1\n",
      "K2  A2  B2   C2   D2\n",
      "K3  A3  B3  NaN  NaN\n",
      "==============================\n"
     ]
    }
   ],
   "execution_count": 45
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-10T07:35:00.843030Z",
     "start_time": "2025-09-10T07:35:00.825179Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 连接多个DataFrame\n",
    "right2 = pd.DataFrame({\n",
    "    'E': ['E0', 'E1', 'E2']\n",
    "}, index=['K0', 'K1', 'K2'])\n",
    "\n",
    "result1 = left.join([right,right2])\n",
    "print(result1)"
   ],
   "id": "d7e606ef2e61761e",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "     A   B    C    D    E\n",
      "K0  A0  B0   C0   D0   E0\n",
      "K1  A1  B1   C1   D1   E1\n",
      "K2  A2  B2   C2   D2   E2\n",
      "K3  A3  B3  NaN  NaN  NaN\n"
     ]
    }
   ],
   "execution_count": 49
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 3. 演示concat()  沿轴连接",
   "id": "f715496d04678e9d"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-10T07:41:08.900890Z",
     "start_time": "2025-09-10T07:41:08.875596Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 创建示例数据\n",
    "df1 = pd.DataFrame({\n",
    "    'A': ['A0', 'A1', 'A2', 'A3'],\n",
    "    'B': ['B0', 'B1', 'B2', 'B3'],\n",
    "    'C': ['C0', 'C1', 'C2', 'C3'],\n",
    "    'D': ['D0', 'D1', 'D2', 'D3']\n",
    "})\n",
    "\n",
    "df2 = pd.DataFrame({\n",
    "    'A': ['A4', 'A5', 'A6', 'A7'],\n",
    "    'B': ['B4', 'B5', 'B6', 'B7'],\n",
    "    'C': ['C4', 'C5', 'C6', 'C7'],\n",
    "    'D': ['D4', 'D5', 'D6', 'D7']\n",
    "})\n",
    "\n",
    "# 默认沿着axis = 0 连接，纵向\n",
    "result_concat_0 = pd.concat([df1, df2])\n",
    "print(f'默认沿着0轴连接\\n{result_concat_0}')\n",
    "\n",
    "\n",
    "# 演示 沿着axis = 1 连接，横向\n",
    "result_concat_1 = pd.concat([df1, df2],axis=1)\n",
    "print(f'沿着1轴连接\\n{result_concat_1}')\n",
    "\n",
    "\n",
    "# 使用keys参数\n",
    "result_concat_2 = pd.concat([df1, df2],keys=['x','y'])\n",
    "print(f'使用keys参数\\n{result_concat_2}')\n",
    "\n",
    "\n",
    "# 忽略索引\n",
    "result_concat_3 = pd.concat([df1, df2],ignore_index=True)\n",
    "print(f'忽略索引\\n{result_concat_3}')"
   ],
   "id": "503acf2b39b2223a",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "默认沿着0轴连接\n",
      "    A   B   C   D\n",
      "0  A0  B0  C0  D0\n",
      "1  A1  B1  C1  D1\n",
      "2  A2  B2  C2  D2\n",
      "3  A3  B3  C3  D3\n",
      "0  A4  B4  C4  D4\n",
      "1  A5  B5  C5  D5\n",
      "2  A6  B6  C6  D6\n",
      "3  A7  B7  C7  D7\n",
      "沿着1轴连接\n",
      "    A   B   C   D   A   B   C   D\n",
      "0  A0  B0  C0  D0  A4  B4  C4  D4\n",
      "1  A1  B1  C1  D1  A5  B5  C5  D5\n",
      "2  A2  B2  C2  D2  A6  B6  C6  D6\n",
      "3  A3  B3  C3  D3  A7  B7  C7  D7\n",
      "使用keys参数\n",
      "      A   B   C   D\n",
      "x 0  A0  B0  C0  D0\n",
      "  1  A1  B1  C1  D1\n",
      "  2  A2  B2  C2  D2\n",
      "  3  A3  B3  C3  D3\n",
      "y 0  A4  B4  C4  D4\n",
      "  1  A5  B5  C5  D5\n",
      "  2  A6  B6  C6  D6\n",
      "  3  A7  B7  C7  D7\n",
      "忽略索引\n",
      "    A   B   C   D\n",
      "0  A0  B0  C0  D0\n",
      "1  A1  B1  C1  D1\n",
      "2  A2  B2  C2  D2\n",
      "3  A3  B3  C3  D3\n",
      "4  A4  B4  C4  D4\n",
      "5  A5  B5  C5  D5\n",
      "6  A6  B6  C6  D6\n",
      "7  A7  B7  C7  D7\n"
     ]
    }
   ],
   "execution_count": 54
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-10T07:45:38.496222Z",
     "start_time": "2025-09-10T07:45:38.472240Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 创建示例数据\n",
    "df1 = pd.DataFrame({\n",
    "    'A': ['A0', 'A1', 'A2', 'A3'],\n",
    "    'B': ['B0', 'B1', 'B2', 'B3'],\n",
    "    'C': ['C0', 'C1', 'C2', 'C3'],\n",
    "    'D': ['D0', 'D1', 'D2', 'D3']\n",
    "})\n",
    "# 列名不同的DataFrame\n",
    "df3 = pd.DataFrame({\n",
    "    'A': ['A8', 'A9'],\n",
    "    'B': ['B8', 'B9'],\n",
    "    'E': ['E8', 'E9'],  # 不同的列\n",
    "    'F': ['F8', 'F9']   # 不同的列\n",
    "})\n",
    "\n",
    "result_concat_4 = pd.concat([df1,df3])\n",
    "print(f'不同列名连接\\n{result_concat_4}')\n",
    "\n",
    "# 内连接方式保留共有的列\n",
    "result_inner_concat = pd.concat([df1,df3],join='inner',ignore_index=True)\n",
    "print(f'内连接方式使用concat\\n{result_inner_concat}')\n"
   ],
   "id": "8b0152dccff73996",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "不同列名连接\n",
      "    A   B    C    D    E    F\n",
      "0  A0  B0   C0   D0  NaN  NaN\n",
      "1  A1  B1   C1   D1  NaN  NaN\n",
      "2  A2  B2   C2   D2  NaN  NaN\n",
      "3  A3  B3   C3   D3  NaN  NaN\n",
      "0  A8  B8  NaN  NaN   E8   F8\n",
      "1  A9  B9  NaN  NaN   E9   F9\n",
      "内连接方式使用concat\n",
      "    A   B\n",
      "0  A0  B0\n",
      "1  A1  B1\n",
      "2  A2  B2\n",
      "3  A3  B3\n",
      "4  A8  B8\n",
      "5  A9  B9\n"
     ]
    }
   ],
   "execution_count": 58
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
